/*
 * Surface.java
 *
 * Created on November 27, 2007, 5:13 PM
 *
 */

package core;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import ui.AnimationCanvas;

/**
 *
 * @author Suraj Sapktoa [ ssapkota<at>gmail<dot>com ]
 * @version $Id: $
 */
public class Surface {
    private String name=null;
    
    private AnimationCanvas ac=null;
    private Set<Point3D> surfacePoints=null;
    
    private MathVector normal=null;
    private Point3D centre=null;
    //illumination (intensity) (supposing all the colours have the same intensity)
    private float I=0.33F;
    
    /** Creates a new instance of Surface
     * The set received through the argument must be a linked set where the points must be in a cyclic order
     */
    public Surface(String name,AnimationCanvas ac,LinkedHashSet<Point3D> pts,Point3D centre) {
        this.name=name;
        this.ac=ac;
        this.surfacePoints=pts;
        this.centre=centre;
    }
    
    public void paint(Graphics2D g2,Component comp){
        Point3D cen=comp.getCentre();
        Iterator iter=surfacePoints.iterator();
        float[] px=new float[3],py=new float[3],pz=new float[3];
        int i=0;
        System.out.print(name+": ");
        while(iter.hasNext()){
            Point3D pt=(Point3D)iter.next();
            px[i]=pt.getPx();
            py[i]=pt.getPy();
            pz[i]=pt.getPz();
            i++;
            if(i==3) break; //3 pts suffice for finding normal
        }
        
        // a,b and c are (positional) vectors in object space ==> 3 points of the plane assuming components centre as origin
        MathVector a=new MathVector(px[0]-cen.getPx(),py[0]-cen.getPy(),pz[0]-cen.getPz());
        MathVector b=new MathVector(px[1]-cen.getPx(),py[1]-cen.getPy(),pz[1]-cen.getPz());
        MathVector c=new MathVector(px[2]-cen.getPx(),py[2]-cen.getPy(),pz[2]-cen.getPz());
        //System.out.print("  a: "+a+"  b: "+b+"  c: "+c);
        // a-b and c-b vectors
        MathVector a_b=new MathVector(a.getI()-b.getI(),a.getJ()-b.getJ(),a.getK()-b.getK());
        MathVector c_b=new MathVector(c.getI()-b.getI(),c.getJ()-b.getJ(),c.getK()-b.getK());
        //System.out.print("a_b: "+a_b+"  c_b: "+c_b);
        this.normal=MathVector.crossProduct(a_b,c_b).getUnitVector();
        //System.out.print(" Normal Vector: "+normal.getUnitVector());
        
        float temp=MathVector.dotProduct(normal,new MathVector(this.centre.getPx(),this.centre.getPy(),this.centre.getPz()).getUnitVector());
        //System.out.print(" N X V ="+temp);
        
        //temp=N.V ==> if temp<0 the surface is visible and paint it
        if(temp>0){
            I=Constants.IaKa + Math.abs(Constants.IdKd*temp); // the intensity of this surface (taking ambient and diffuse reflection only)
            //we wont consider Specular reflection as it is only preferred in curved surface.
            int[] dx=new int[4],dy=new int[4];
            iter=surfacePoints.iterator();
            i=0;
            while(iter.hasNext()){
                Point3D p=(Point3D) iter.next();
                dx[i]=p.getDx();
                dy[i]=p.getDy();
                i++;
            }
            g2.setColor(new Color(I,I,I));
            Polygon poly= new Polygon(dx,dy,4);
            g2.fillPolygon(poly);
            System.out.print(" [Visibility: Visible]  [Intensity="+I+"]");
            g2.setColor(new Color(0,0,0));
            g2.drawPolygon(poly);
            if(this.getName().equals("Front Face") && comp.getName().equals("Head")){
                //if fornt face of head is visible paint face-components too.
                ac.getRobot().PaintFace(g2);
            }
        }
        else {
            System.out.print(" [Visibility: Not Visible]");
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
